package com.octopus.kernal.ui.builder;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;

import com.octopus.kernal.model.BaseStruct;
import com.octopus.kernal.service.BusinessModelService;
import com.octopus.kernal.ui.element.BaseElement;
import com.octopus.kernal.ui.element.CheckboxElement;
import com.octopus.kernal.ui.element.SelectElement;
import com.octopus.kernal.util.xml.Column;
import com.octopus.kernal.util.xml.ElementDetail;
import com.octopus.kernal.util.xml.Entity;
import com.octopus.kernal.util.xml.Field;
import com.octopus.kernal.util.xml.Action;

@Service
public class QueryTableBuilder<T extends BaseStruct> {
	
	private String sp = System.getProperty("line.separator");
	
	@Autowired
	private BusinessModelService businessModelService;
	
	public String build(HttpServletRequest request, String entityName, List<T> entities, String fieldSort, MessageSource messageSource){
		return this.build(request, entityName, entities, fieldSort, null, null, null, messageSource);
	}
	
	public String build(HttpServletRequest request, String entityName, List<T> entities, String fieldSort, 
			List<String> disabledFields, String onDbClick, String onSort, MessageSource messageSource){
		Entity entity = this.businessModelService.getEntityByName(entityName);
		if(entity == null)
			return "";
		StringBuffer html = new StringBuffer();
		// TH
		html.append("<tr>" + sp);
		for(Field field : entity.getFields()){
			if(field.getElementDetail() != null && field.getElementDetail().getListed()){
				if(disabledFields != null && disabledFields.contains(field.getName()))
					continue;
				html.append("<th>" + sp);
				String key = "label." + entity.getAlias() + ".field." + field.getName();
				String way = "asc";
				String img = "";
				if(fieldSort != null && fieldSort.indexOf(":") > 0 && field.getName().equals(fieldSort.substring(0, fieldSort.indexOf(":")))){
					String w = fieldSort.substring(fieldSort.indexOf(":") + 1);
					if("asc".equals(w)){
						way = "desc";
						img = "<img width=\"13px\" height=\"13px\" src=\"" + request.getContextPath() + "/img/asc.png\">" + sp;
					}else if("desc".equals(w)){
						way = "reset";
						img = "<img width=\"13px\" height=\"13px\" src=\"" + request.getContextPath() + "/img/desc.png\">" + sp;
					}
				}
				if(field.getColumn().getManyToMany() == null){
					html.append("<a href=\"javascript:" + (null==onSort?"onSort":onSort) + "('" + field.getName() + "','" + way + "')\">");
				}
				html.append(messageSource.getMessage(key, new Object[] { }, LocaleContextHolder.getLocale()) + sp);
				html.append("</a>" + sp);
				html.append(img);
				html.append("</th>" + sp);
			}
		}
		if(entity.getActions() != null && !(disabledFields != null && disabledFields.contains("_actions"))){
			html.append("<th>" + sp);
			html.append(messageSource.getMessage("label.common.action", new Object[] { }, LocaleContextHolder.getLocale()) + sp);
			html.append("</th>" + sp);
		}
		html.append("</tr>" + sp);
		// TR
		if(entities == null)
			return html.toString();
		for(T struct : entities){
			html.append("<tr style=\"cursor:hand\" ondblclick=\"javascript:" + (null==onDbClick?"onView":onDbClick) + "('" + struct.getId()+ "')\">" + sp);
			for(Field field : entity.getFields()){
				ElementDetail element = field.getElementDetail();
				Column column = field.getColumn();
				if(element == null || !element.getListed())
					continue;
				if(disabledFields != null && disabledFields.contains(field.getName()))
					continue;
				html.append("<td ");
				Object value = struct.getAttributeValues().get(field.getName());
				String str = "";
				if(value == null){
					
				}else if(value instanceof String){
					if(element.getSelectElement() != null){
						if(StringUtils.isNotBlank((String)value))
							str = messageSource.getMessage("common.single.select." + element.getSelectElement().getLabelProperty() + "." + value, new Object[] { }, LocaleContextHolder.getLocale());
					}else{
						str = BaseElement.getTranslationValue((String)value);
					}
				}else if(value instanceof Integer || value instanceof Long || value instanceof Double){
					html.append("align=\"right\"");
					if(element.getSelectElement() != null){
						str = messageSource.getMessage("common.single.select." + element.getSelectElement().getLabelProperty() + "." + value, new Object[] { }, LocaleContextHolder.getLocale());
					}else if(column.getType().equals("Percent")){
						str = String.valueOf(value) + "%";
					}else{
						str = String.valueOf(value);
					}
				}else if(value instanceof Boolean){
					if((Boolean)value)
						str = messageSource.getMessage("label.common.yes", new Object[] { }, LocaleContextHolder.getLocale());
					else
						str = messageSource.getMessage("label.common.no", new Object[] { }, LocaleContextHolder.getLocale());
				}else if(value instanceof Date){
					SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", new Locale("en"));
					if(column.getType().equals("Time"))
						format = new SimpleDateFormat("yyyy-MM-dd HH:mm", new Locale("en"));
					str = format.format((Date)value);
				}else if(value instanceof BaseStruct){
					SelectElement select = field.getElementDetail().getSelectElement();
					if(select != null){
						str = BaseElement.getTranslationValue((String)((BaseStruct)(value)).getAttributeValues().get(select.getLabelProperty()));
					}
				}else if(value instanceof Set){
					CheckboxElement checkbox = field.getElementDetail().getCheckboxElement();
					checkbox.setReadonly(true);
					checkbox.setMessageSource(messageSource);
					checkbox.setValue(value);
					str = checkbox.toString();
				}
				html.append(">" + sp);
				if(StringUtils.isNotBlank(element.getLink())){
					String url = request.getContextPath() + "/" + entity.getAlias() + "/" + element.getLink();
					html.append("<a href=\"javascript:onActionGet('" + url + "', '" + struct.getId() + "','')\">");
					html.append(str);
					html.append("</a>" + sp);
				}else{
					html.append(str + sp);
				}
				html.append("</td>" + sp);
			}
			// Actions	
			if(entity.getActions() != null && !(disabledFields != null && disabledFields.contains("_actions"))){
				html.append("<td align='left'>" + sp);
				for(Action action : entity.getActions()){
					if(action.getPost() || "query".equals(action.getKey()))
						continue;
					String url = action.getKey();
					String label = "label.common.action." + action.getKey();
					if(action.getCustomized()){
						url = "x/" + url;
						label = "label." + entity.getAlias() + ".action." + action.getKey();
					}
					url = request.getContextPath() + "/" + entity.getAlias() + "/" + url;
					if((action.getPermission()==null?true:(SecurityUtils.getSubject().isPermittedAll(action.getPermission().split(",")))) 
							&& action.getShowButton() 
							&& businessModelService.isActionAllowed(struct, action.getRule())){
						String module = action.getCustomized()?entity.getAlias():"common";
						String confirm = action.getConfirm()?messageSource.getMessage("label." + module + ".confirm." + action.getKey() + "", new Object[] { }, LocaleContextHolder.getLocale()):"";
						html.append("<input type=\"button\" onclick=\"onActionGet('" + url + "', '" + struct.getId() + "','" + confirm + "')\" " +
								"value=\"" + messageSource.getMessage(label + "", new Object[] { }, LocaleContextHolder.getLocale()) + "\" >");
						html.append("&nbsp;");
					}
				}
				html.append("</td>" + sp);
			}		
			html.append("</tr>" + sp);
		}
		return html.toString();
	}

}
